using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.IO;
using System.IO.Compression;
using System.Configuration;
using DNAide.Core;
using DNAide.IO;
using DNAide.Configuration;

namespace DNAide.Web
{
	public class HttpCompressionModule : IHttpModule
	{

		private object _lock = new object();

		#region IHttpModule Members

		/// <summary></summary>
		public void Init(HttpApplication context)
		{
			if (context == null)
				return;

			if (!DNAideConfigurationSettings.Web.HttpCompressionModule.Enabled)
				return;

			context.PostReleaseRequestState += new EventHandler(context_PostReleaseRequestState);

		}


		/// <summary></summary>
		public void Dispose() { }

		#endregion

		void context_PostReleaseRequestState(object sender, EventArgs e)
		{
			HttpApplication app = sender as HttpApplication;

			if (app == null || app.Server == null)
				return;

			// Current module does not compress webresources or asp.net ajax
			if (app.Context.Request.Path.Contains("WebResource.axd") || app.Request["HTTP_X_MICROSOFTAJAX"] != null)
				return;

			foreach (HttpCompressionModuleMimeTypeConfig mimeTypeConfig in DNAideConfigurationSettings.Web.HttpCompressionModule.MimeTypes)
			{
				if (mimeTypeConfig.MimeType == app.Response.ContentType)
				{
					if (!mimeTypeConfig.Enabled)
						return;

					// Apply rules first
					if (mimeTypeConfig.Rules.Count > 0)
					{
						IEnumerator<HttpCompressionModuleRuleConfig> ruleEnum = mimeTypeConfig.Rules.GetEnumerator();
						while (ruleEnum.MoveNext())
						{
							if (ruleEnum.Current.UrlMatchExpressionRegex.IsMatch(app.Request.RawUrl))
							{
								// Apply rule specific options
								if (!ruleEnum.Current.Enabled)
									return;
								ApplyCompression(app);
								return;
							}
						}
					}

					// Apply generic options
					ApplyCompression(app);
					return;
				}
			}

		}

		void ApplyCompression(HttpApplication app)
		{
			app.Context.Response.Cache.VaryByHeaders["Accept-Encoding"] = true;
			string acceptedTypes = app.Request.Headers["Accept-Encoding"];

			// if we couldn't find the header so return
			if (acceptedTypes == null)
				return;


			// Determine what compression algorithm we can actually deal with 
			if (RequestAide.IsGZipSupported())
			{
				app.Response.AppendHeader("Content-Encoding", "gzip");
				app.Response.Filter = new GZipStream(app.Response.Filter, CompressionMode.Compress);
			}
			else if (RequestAide.IsDeflateSupported())
			{
				app.Response.AppendHeader("Content-Encoding", "deflate");
				app.Response.Filter = new DeflateStream(app.Response.Filter, CompressionMode.Compress);
			}

		}

	}


}
